package com.rampage.utils;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.*;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HttpUtil {
	Logger mLogger = LogManager.getLogger(HttpUtil.class);
	static HttpUtil mHttpUtil = null;
	String TAG = "HttpUtil";
	private HttpResponse response;

	private int connectionTimeout = 30000;// 连接超时
	private int soTimeout = 50000;// 数据传输超时

	public static HttpUtil getInstance() {
		if (mHttpUtil == null) {
			return new HttpUtil();
		}
		return mHttpUtil;
	}

	public HttpResponse getResponse() {
		return response;
	}
	
	protected JSONObject getJson(HttpResponse httpResponse)
			throws ParseException, IOException, JSONException {
		if (httpResponse != null
				&& httpResponse.getStatusLine().getStatusCode() == 200) {
			String result = EntityUtils.toString(httpResponse.getEntity(),
					"GB2312");// 设置接收字符集
			JSONObject json = new JSONObject(result);
			return json;
		}
		return null;
	}

	/**
	 * 通过http POST获取JSON
	 * 
	 * @param uri
	 * @param params
	 * @return
	 * @throws JSONException
	 * @throws IOException
	 * @throws ParseException
	 */
	public JSONObject getJson(String uri, Map<String, String> params)
			throws ParseException, IOException, JSONException {
		HttpClient client = getHttpClient(uri);
		HttpUriRequest request = getPostRequest(uri, params);// 使用post方式发送
		HttpResponse response = getHttpResponse(client, request);
		return this.getJson(response);
	}

	/**
	 * 通过http get获取JSON
	 * 
	 * @param uri
	 * @param params
	 * @return
	 * @throws JSONException
	 * @throws IOException
	 * @throws ParseException
	 */
	public JSONObject getJsonForGet(String uri, Map<String, String> params)
			throws ParseException, IOException, JSONException {
		HttpClient client = getHttpClient(uri);
		HttpUriRequest request = getGetRequest(uri, params);// 使用post方式发送
		HttpResponse response = getHttpResponse(client, request);
		return this.getJson(response);
	}

	protected HttpClient getHttpClient(String uri) {
		HttpClient httpclient = null;
		if (uri.indexOf("https") == 0) {
			httpclient = getHttpsClient();// 使用https 调用
		} else {
			httpclient = getHttpClient();
		}
		httpclient.getParams().setParameter(
				CoreConnectionPNames.CONNECTION_TIMEOUT, connectionTimeout);// 连接时间10s
		httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
				soTimeout);// 数据传输时间25s
		return httpclient;
	}

	protected HttpClient getHttpClient() {
		return new DefaultHttpClient();
	}

	/**
	 * 获取httpPost 请求
	 * 
	 * @param uri
	 * @param params
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public HttpUriRequest getPostRequest(String uri, Map<String, String> params)
			throws UnsupportedEncodingException {
		List<NameValuePair> qparams = new ArrayList<NameValuePair>();
		for (String paramName : params.keySet()) {
			qparams.add(new BasicNameValuePair(paramName, params.get(paramName)));
		}
		HttpPost request = new HttpPost(uri);
		request.setEntity(new UrlEncodedFormEntity(qparams, HTTP.UTF_8));
		return request;
	}

	/**
	 * 获取HttpGet 请求
	 * 
	 * @param uri
	 * @param params
	 * @return
	 */
	protected HttpUriRequest getGetRequest(String uri, Map<String, String> params) {
		List<NameValuePair> qparams = new ArrayList<NameValuePair>();
		for (String paramName : params.keySet()) {
			qparams.add(new BasicNameValuePair(paramName, params.get(paramName)));
		}
		String paramString = URLEncodedUtils.format(qparams, HTTP.UTF_8);
		String requestUrl = (paramString.isEmpty()) ? uri
				: (uri + "?" + paramString);
		HttpGet httpRequst = new HttpGet(requestUrl);
		return httpRequst;
	}


    /** 
     * 下载文件保存到本地 
     *  
     * @param path 
     *            文件保存位置 
     * @param url 
     *            文件地址 
     * @throws Exception 
     */  
    public void downloadFile(String path, String url) throws Exception {      
        HttpClient client = null;  
        try {  
        	client = getHttpClient(url);
    		HttpUriRequest request = getGetRequest(url, new HashMap<String, String>());// 使用post方式发送
    		HttpResponse response = getHttpResponse(client, request);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {  
                byte[] result = EntityUtils.toByteArray(response.getEntity());  
                BufferedOutputStream bw = null;  
                try {  
                    // 创建文件对象  
                    File f = new File(path);  
                    // 创建文件路径  
                    if (!f.getParentFile().exists())  
                        f.getParentFile().mkdirs();  
                    // 写入文件  
                    bw = new BufferedOutputStream(new FileOutputStream(f,false));  
                    bw.write(result);  
                } catch (Exception e) {  
                    mLogger.error("保存文件错误,path=" + path + ",url=" + url, e);
                    throw e;
                } finally {  
                    try {  
                        if (bw != null)  
                            bw.close();  
                    } catch (Exception e) {  
                        mLogger.error("finally BufferedOutputStream shutdown close", e);  
                    }  
                }  
            }  
            // 如果失败  
            else {  
               throw new Exception("状态码:"+response.getStatusLine().getStatusCode());
            }  
        } catch (Exception e) {  
            mLogger.error("下载文件保存到本地异常,path=" + path + ",url=" + url, e); 
            throw e;
        }finally {  
            try {
                client.getConnectionManager().shutdown();  
            } catch (Exception e) {  
                mLogger.error("finally HttpClient shutdown error", e);  
            }  
        }  
    }  
	
	/**
	 * 发送 request 返回 respone
	 * 
	 * @param client
	 * @param request
	 * @return
	 * @throws IOException
	 * @throws ClientProtocolException
	 */
	protected HttpResponse getHttpResponse(HttpClient client,
			HttpUriRequest request) throws ClientProtocolException, IOException {
		return client.execute(request);
	}

	// HTTPS...
	protected HttpClient getHttpsClient() {

		// 把咱的证书库作为信任证书库
		SSLSocketFactory socketFactory = null;
		try {
			socketFactory = new SSLSocketFactory(this.getSSLKeyStore());
			socketFactory.setHostnameVerifier(new AllowAllHostnameVerifier());// 不需要证书认证
		} catch (KeyManagementException e) {
			mLogger.error(TAG, "GetHttpsClient " + e.getLocalizedMessage());
		} catch (UnrecoverableKeyException e) {
			mLogger.error(TAG, "GetHttpsClient " + e.getLocalizedMessage());
		} catch (NoSuchAlgorithmException e) {
			mLogger.error(TAG, "GetHttpsClient " + e.getLocalizedMessage());
		} catch (KeyStoreException e) {
			mLogger.error(TAG, "GetHttpsClient " + e.getLocalizedMessage());
		}
		Scheme sch = new Scheme("https", socketFactory, 443);
		// 完工
		HttpClient httpClient = new DefaultHttpClient();
		httpClient.getConnectionManager().getSchemeRegistry().register(sch);
		return httpClient;
	}

	
	/**
	 * 注意： 只能DC 初始化环境后才能进行。
	 * @return
	 */
	protected KeyStore getSSLKeyStore() {
		InputStream ins = null;
		try {
			ins = HttpUtil.class.getClassLoader()
			.getResourceAsStream("xuechuang.cer");
			// 读取证书
			CertificateFactory cerFactory = CertificateFactory
					.getInstance("X.509");
			Certificate cer = cerFactory.generateCertificate(ins);
			// 创建一个证书库，并将证书导入证书库
			KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
			keyStore.load(null, null);
			keyStore.setCertificateEntry("trust", cer);
			return keyStore;
		} catch (IOException e) {
			mLogger.error(TAG, "getSSLKeyStore " + e.getLocalizedMessage());
		} catch (CertificateException e) {
			mLogger.error(TAG, "getSSLKeyStore " + e.getLocalizedMessage());
		} catch (KeyStoreException e) {
			mLogger.error(TAG, "getSSLKeyStore " + e.getLocalizedMessage());
		} catch (NoSuchProviderException e) {
			mLogger.error(TAG, "getSSLKeyStore " + e.getLocalizedMessage());
		} catch (NoSuchAlgorithmException e) {
			mLogger.error(TAG, "getSSLKeyStore " + e.getLocalizedMessage());
		} finally {
			try {
				ins.close();
			} catch (IOException e) {
				mLogger.error(TAG, "GetHttpsClient" + e.getLocalizedMessage());
			}
		}
		return null;
	}

	public void pack(String url) {

		try {
			HttpClient httpClient = new DefaultHttpClient();
			HttpParams httpParams = httpClient.getParams();
			httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
					Integer.valueOf(3000));
			httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT,
					Integer.valueOf(5000));
			HttpPost httpRequest = new HttpPost(url);
			response = httpClient.execute(httpRequest);
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void parse(String dataBasePath) {
		try {
			if (getResponse() != null
					&& getResponse().getStatusLine().getStatusCode() == 200) {

				InputStream is = getResponse().getEntity().getContent();
				OutputStream os = new FileOutputStream(dataBasePath);
				byte[] buffer = new byte[1024];
				int length;
				while ((length = is.read(buffer)) > 0) {
					os.write(buffer, 0, length);
				}
				os.flush();
				os.close();
				is.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
}
